package tjs.study.notes.dotest.jvm.classload.encode;

import tjs.study.notes.dotest.TjsStudyNotesApplication;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * Created by Nicky.Tang on 2021/10/20 2:24 下午
 * 加密解密
 *
 * @since 02.12.10
 */
public class DoTestOfEncryption {
    static final int ENCODE_KEY = 123456789;

    public static void main(String[] args) throws Exception {
//        testEncodeStr();
        // 1.先加密目标class
        encodeFile(TjsStudyNotesApplication.work_space+"/jvm/classload/encode/UserService.class");

        // 2.再使用自定义的解密类加载器加载目标class
        DecodeClassLoader decodeClassLoader = new DecodeClassLoader(TjsStudyNotesApplication.work_space_pre+"/src/main/java");
        Class<?> userServiceClass = decodeClassLoader.loadClass("tjs.study.notes.dotest.jvm.classload.encode.UserService");
        Object userService =  userServiceClass.newInstance();
        userServiceClass.getDeclaredMethod("login").invoke(userService);
    }

    public static void testEncodeStr() {
        String sourceStr = "Hellow world";
        String encode = Xor(sourceStr, ENCODE_KEY);//加密
        System.out.println(encode);//
        String decode = Xor(encode, ENCODE_KEY);//解密
        System.out.println(decode);//Hellow world
    }

    public static String Xor(String input, int key) {
        char[] chs = input.toCharArray();
        for (int i = 0; i < chs.length; i++) {
            chs[i] = (char) (chs[i] ^ key);
        }
        return new String(chs);
    }

    public static void encodeFile(String fileName) {
        System.out.println("开始加密文件：" + fileName);
        try (FileInputStream fileInputStream = new FileInputStream(new File(fileName));
             FileOutputStream outputStream = new FileOutputStream(new File(fileName + "_encode"))) {
            int len = 0;
            while ((len = fileInputStream.read()) != -1) {
                // fixme 加密-首次异或运算
                outputStream.write(len ^ DoTestOfEncryption.ENCODE_KEY);
            }
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
